package com.xbongbong.saas.service.toolbox.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaySheetTypeEnum;
import com.xbongbong.paas.enums.PaymentSheetTypeEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.pojo.dto.AggSumDTO;
import com.xbongbong.paas.pojo.dto.FormDataSummaryDTO;
import com.xbongbong.paas.pojo.dto.FormDataUpdateGetDTO;
import com.xbongbong.paas.pojo.dto.PlanFieldAttrDTO;
import com.xbongbong.paas.pojo.vo.AggSumVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BusinessTypeErrorCodeEnum;
import com.xbongbong.pro.service.toolbox.statistic.help.SystemChartHelp;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.InvoiceConstant;
import com.xbongbong.saas.constant.PaymentConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.PayPlanSheetEntityExt;
import com.xbongbong.saas.domain.entity.ext.PaymentEntityExt;
import com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt;
import com.xbongbong.saas.enums.PlanTotalTypeEnum;
import com.xbongbong.saas.enums.SheetAloneEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.InvoiceEnum;
import com.xbongbong.saas.enums.business.PayPlanEnum;
import com.xbongbong.saas.enums.business.PayRelationshipEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PaymentEnum;
import com.xbongbong.saas.enums.business.PaymentRelationshipEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.PurchaseInvoiceEnum;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.PayPlanSheetModel;
import com.xbongbong.saas.model.PaymentSheetModel;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 * 应用模块名称<p>
 * 代码描述<p>
 * Company: 逍邦网络科技有限公司<p>
 *
 * @author chenshan
 * @version v1.0
 * @since 2020-03-12 14:57
 */
@Component
public class FundMoneyHelp {

    private static final Logger LOG = LoggerFactory.getLogger(FundMoneyHelp.class);

    @Resource
    private EsHelper esHelper;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private PayPlanSheetModel paySheetModel;
    @Resource
    private SystemChartHelp systemChartHelp;
    @Resource
    private IndexTypeModel indexTypeModel;

    /**
     * 计算重复金额
     * @param formDataUpdateGetDTO
     * @param explainMap
     * @param businessType
     * @return
     * @throws XbbException
     */
    public Double getCoverCalAmount(FormDataUpdateGetDTO formDataUpdateGetDTO, Map<String, FieldAttrEntity> explainMap, Integer businessType) throws XbbException {
        //合同金额=(预收款核销金额+回款单核销金额)+回款计划金额-回款计划已收金额-回款计划已坏金额+(坏账金额+已红冲金额-有红冲回款单的回款计划金额)
        //处理合同的新建时：核销预收款、回款单、回款计划的权限
        //拿到总的核销金额
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        PlanFieldAttrDTO planFieldAttrDTO = new PlanFieldAttrDTO(formDataUpdateGetDTO.getLoginUser(), explainMap, xbbRefTypeEnum);
        Double redAndBadAmount = 0D;
        String linkSheetAttr = getSheetLinkAttr(xbbRefTypeEnum);
        String linkPlanAttr = getPlanLinkAttr(xbbRefTypeEnum);
        Double totalWriteOffAmount = getSheetTotalWriteOffAmount(planFieldAttrDTO.getLinkSheetBusinessTypeEnum(), formDataUpdateGetDTO, !planFieldAttrDTO.getHasSheetPerm(), !planFieldAttrDTO.getHasWriteOffPerm(), linkSheetAttr);
        if ( !planFieldAttrDTO.getHasSheetPerm() ) {
            //拿到坏账和红冲金额减有红冲回款单的回款计划金额
            redAndBadAmount = getSheetRedAndBadAmount(planFieldAttrDTO.getLinkSheetBusinessTypeEnum(), formDataUpdateGetDTO, true, true, linkSheetAttr);
        }
        Double planAmount = 0D;
        if ( !planFieldAttrDTO.getHasPlanPerm() ) {
            planAmount = getPlanTotalRealAmount(planFieldAttrDTO.getLinkPlanBusinessTypeEnum(), formDataUpdateGetDTO, linkPlanAttr, getPlanTotalAttr(xbbRefTypeEnum, PlanTotalTypeEnum.NORMAL));
        }
        //拿到重复的已收金额
        Double realAmount = getPlanTotalRealAmount(planFieldAttrDTO.getLinkPlanBusinessTypeEnum(), formDataUpdateGetDTO, linkPlanAttr, getPlanTotalAttr(xbbRefTypeEnum, PlanTotalTypeEnum.FINISH_TOTAL));
        //拿到重复的坏账金额
        Double badAmount = getPlanTotalRealAmount(planFieldAttrDTO.getLinkPlanBusinessTypeEnum(), formDataUpdateGetDTO, linkPlanAttr, getPlanTotalAttr(xbbRefTypeEnum, PlanTotalTypeEnum.BAD_TOTAL));
        LOG.info("realAmount:"+realAmount+",badAmount:"+badAmount+",redAndBadAmount:"+redAndBadAmount+",planAmount:"+planAmount+",totalWriteOffAmount:"+totalWriteOffAmount);
    
        Double coverCalAmount = Arith.sub(Arith.sub(Arith.sub(Arith.add(realAmount, badAmount), redAndBadAmount), planAmount), totalWriteOffAmount);
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                coverCalAmount = attrDecimalPrecisionHelper.setPrecision(coverCalAmount,explainMap, ContractEnum.AMOUNT.getAttr());
                break;
            case PURCHASE:
                coverCalAmount = attrDecimalPrecisionHelper.setPrecision(coverCalAmount,explainMap, PurchaseEnum.TOTAL_MONEY.getAttr());
                break;
        }
        return coverCalAmount;
    }
    
    /**
     * 获取导入时计算重复值, 2020/1/28现在把采购合同和合同分开来处理，采购合同还是就判断一个菜单权限
     * @param formDataUpdateGetDTO
     * @param explainMap
     * @param businessType
     * @param isImport
     * @return
     * @throws XbbException
     */
    public Double getImportCoverCalAmount(Double payTotalAmount,FormDataUpdateGetDTO formDataUpdateGetDTO, Map<String, FieldAttrEntity> explainMap, Integer businessType,Integer isImport,
                                          List<Long> paymentFlowStatusIdList, List<Long> paymentSheetFlowStatusIdList, List<Long> writeOffPrepaymentFlowStatusIdList) throws XbbException {
        Long taskId = formDataUpdateGetDTO.getTaskId();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        PlanFieldAttrDTO planFieldAttrDTO = new PlanFieldAttrDTO(formDataUpdateGetDTO.getLoginUser(), explainMap, xbbRefTypeEnum);
        Double totalWriteOffAmount = 0D;
        Double redAndBadAmount = 0D;
        String linkSheetAttr = getSheetLinkAttr(xbbRefTypeEnum);
        String linkPlanAttr = getPlanLinkAttr(xbbRefTypeEnum);
        boolean hasSheetFlag = true;
        boolean hasWriteOffFlag = true;
        boolean hasPlanFlag = true;
        if (Objects.equals(XbbRefTypeEnum.PURCHASE, xbbRefTypeEnum)) {
            hasSheetFlag = !planFieldAttrDTO.getHasSheetPerm();
            hasWriteOffFlag = !planFieldAttrDTO.getHasWriteOffPerm();
            hasPlanFlag = !planFieldAttrDTO.getHasPlanPerm();
        }else {
            //没有回款单菜单权限/付款单并且不在审批中 或者 不管有没有回款单/付款单权限但是在审批中，但是回款单前端没有拿到真正有用的数据传过来(用于看不到回款单菜单/付款单权限的人编辑进审批，下一个审批人不管有没有回款单菜单权限)
            hasSheetFlag = (!planFieldAttrDTO.getHasSheetPerm() && Objects.isNull(taskId)) || (Objects.nonNull(taskId) && CollectionsUtil.isEmpty(paymentSheetFlowStatusIdList));
            //预收款/预付款同上
            hasWriteOffFlag = (!planFieldAttrDTO.getHasWriteOffPerm() && Objects.isNull(taskId)) || (Objects.nonNull(taskId) && CollectionsUtil.isEmpty(writeOffPrepaymentFlowStatusIdList));
            //回款计划/付款计划同上
            hasPlanFlag = (!planFieldAttrDTO.getHasPlanPerm() && Objects.isNull(taskId)) || (Objects.nonNull(taskId) && CollectionsUtil.isEmpty(paymentFlowStatusIdList));
        }
        if (Objects.equals(isImport, 1)) {
            hasSheetFlag = true;
            hasWriteOffFlag = true;
            hasPlanFlag = true;
        }
        /*boolean hasSheetFlag = !planFieldAttrDTO.getHasSheetPerm() || Objects.equals(isImport, 1);
        boolean hasWriteOffFlag = !planFieldAttrDTO.getHasWriteOffPerm() || Objects.equals(isImport, 1);*/
        totalWriteOffAmount = getSheetTotalWriteOffAmount(planFieldAttrDTO.getLinkSheetBusinessTypeEnum(), formDataUpdateGetDTO, hasSheetFlag, hasWriteOffFlag, linkSheetAttr);
        Double planAmount = 0D;

        if ( hasPlanFlag ) {
            planAmount = getPlanTotalRealAmount(planFieldAttrDTO.getLinkPlanBusinessTypeEnum(), formDataUpdateGetDTO, linkPlanAttr, getPlanTotalAttr(xbbRefTypeEnum, PlanTotalTypeEnum.NORMAL));
        }
        //拿到重复的已收金额
        Double realAmount = getPlanTotalRealAmount(planFieldAttrDTO.getLinkPlanBusinessTypeEnum(), formDataUpdateGetDTO, linkPlanAttr, getPlanTotalAttr(xbbRefTypeEnum, PlanTotalTypeEnum.FINISH_TOTAL));
        //拿到重复的坏账金额
        Double badAmount = getPlanTotalRealAmount(planFieldAttrDTO.getLinkPlanBusinessTypeEnum(), formDataUpdateGetDTO, linkPlanAttr, getPlanTotalAttr(xbbRefTypeEnum, PlanTotalTypeEnum.BAD_TOTAL));
        //拿到坏账和红冲金额
        if ( Objects.equals(isImport, 1) ) {
            redAndBadAmount = getSheetRedAndBadAmount(planFieldAttrDTO.getLinkSheetBusinessTypeEnum(), formDataUpdateGetDTO, true, true, linkSheetAttr);
        }
        LOG.info("formDataUpdateGetDTO:"+formDataUpdateGetDTO.getDataId()+",payTotalAmount:"+payTotalAmount+",realAmount:"+realAmount+",badAmount:"+badAmount+",redAndBadAmount:"+redAndBadAmount+",planAmount:"+planAmount+",totalWriteOffAmount:"+totalWriteOffAmount+"isImport:"+isImport);
    
        Double coverCalAmount = Arith.sub(payTotalAmount, Arith.sub(Arith.sub(Arith.sub(Arith.add(realAmount, badAmount), redAndBadAmount), planAmount), totalWriteOffAmount));
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                coverCalAmount = attrDecimalPrecisionHelper.setPrecision(coverCalAmount,explainMap, ContractEnum.AMOUNT.getAttr());
                break;
            case PURCHASE:
                coverCalAmount = attrDecimalPrecisionHelper.setPrecision(coverCalAmount,explainMap, PurchaseEnum.TOTAL_MONEY.getAttr());
                break;
        }
        return coverCalAmount;
    }
    
    /**
     * 统计在应收款页面已经回款的金额
     * @param formDataUpdateGetDTO
     * @param businessType
     * @return
     */
    public Double getWriteOffAmount(FormDataUpdateGetDTO formDataUpdateGetDTO, Integer businessType) throws XbbException{
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        String linkSheetAttr = getSheetLinkAttr(xbbRefTypeEnum);
        String linkPlanAttr = getPlanLinkAttr(xbbRefTypeEnum);
        
        Double totalWriteOffAmount = getSheetTotalWriteOffAmount(getSheetTypeEnum(xbbRefTypeEnum), formDataUpdateGetDTO,true,true,linkSheetAttr);
        //计算重复已收金额
        Double realAmount = getPlanTotalRealAmount(getPlanTypeEnum(xbbRefTypeEnum),formDataUpdateGetDTO, linkPlanAttr,getPlanTotalAttr(xbbRefTypeEnum,PlanTotalTypeEnum.FINISH_TOTAL));
        //计算重复的坏账金额
        Double badAmount = getPlanTotalRealAmount(getPlanTypeEnum(xbbRefTypeEnum),formDataUpdateGetDTO, linkPlanAttr, getPlanTotalAttr(xbbRefTypeEnum,PlanTotalTypeEnum.BAD_TOTAL));
        //拿到坏账和红冲金额
        Double redAndBadAmount = getSheetRedAndBadAmount(getSheetTypeEnum(xbbRefTypeEnum),formDataUpdateGetDTO,true,true,linkSheetAttr);
    
        return Arith.sub(Arith.sub(Arith.add(realAmount, badAmount), redAndBadAmount),totalWriteOffAmount);
    }
    
    /**
     * 统计在回/付款计划保存时需要校验的金额
     * @param formDataUpdateGetDTO
     * @param businessType
     * @return
     * @throws XbbException
     */
    public Double getCheckAmount(FormDataUpdateGetDTO formDataUpdateGetDTO, Integer businessType,Double paymentAmount) throws XbbException {
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        String linkSheetAttr = getSheetLinkAttr(xbbRefTypeEnum);
        String linkPlanAttr = getPlanLinkAttr(xbbRefTypeEnum);
        
        Double totalWriteOffAmount = getSheetTotalWriteOffAmount(getSheetTypeEnum(xbbRefTypeEnum), formDataUpdateGetDTO,true,true,linkSheetAttr);
        //拿到重复的已收金额
        Double realAmount = getPlanTotalRealAmount(getPlanTypeEnum(xbbRefTypeEnum),formDataUpdateGetDTO, linkPlanAttr,getPlanTotalAttr(xbbRefTypeEnum,PlanTotalTypeEnum.FINISH_TOTAL));
        //拿到重复的坏账金额
        Double badAmount = getPlanTotalRealAmount(getPlanTypeEnum(xbbRefTypeEnum),formDataUpdateGetDTO, linkPlanAttr, getPlanTotalAttr(xbbRefTypeEnum,PlanTotalTypeEnum.BAD_TOTAL));
        //拿到坏账和红冲金额
        Double redAndBadAmount = getSheetRedAndBadAmount(getSheetTypeEnum(xbbRefTypeEnum),formDataUpdateGetDTO,true,true,linkSheetAttr);
        return Arith.add(Arith.sub(Arith.sub(Arith.add(paymentAmount,totalWriteOffAmount),realAmount),badAmount),redAndBadAmount);
    }
    
    /**
     * 根据业务类型获取当前是回款单还是付款单
     * @param xbbRefTypeEnum
     * @return
     */
    private XbbRefTypeEnum getSheetTypeEnum(XbbRefTypeEnum xbbRefTypeEnum) {
        XbbRefTypeEnum businessTypeEnum = null;
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                businessTypeEnum = XbbRefTypeEnum.PAYMENT_SHEET;
                break;
            case PURCHASE:
                businessTypeEnum = XbbRefTypeEnum.PAY_SHEET;
                break;
            default:
                break;
        }
        return businessTypeEnum;
    }
    
    /**
     * 根据业务类型获取当前是应收款还是付款计划
     * @param xbbRefTypeEnum
     * @return
     */
    private XbbRefTypeEnum getPlanTypeEnum(XbbRefTypeEnum xbbRefTypeEnum) {
        XbbRefTypeEnum businessTypeEnum = null;
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                businessTypeEnum = XbbRefTypeEnum.PAYMENT;
                break;
            case PURCHASE:
                businessTypeEnum = XbbRefTypeEnum.PAY_PLAN;
                break;
            default:
                break;
        }
        return businessTypeEnum;
    }
    
    /**
     * 根据业务类型和需要统计的业务类型确定需要统计的应收款/付款计划字段
     * @param xbbRefTypeEnum
     * @param planTotalTypeEnum
     * @return
     * @throws XbbException
     */
    private String getPlanTotalAttr(XbbRefTypeEnum xbbRefTypeEnum, PlanTotalTypeEnum planTotalTypeEnum) throws XbbException {
        String linkAttr = null;
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                switch (planTotalTypeEnum) {
                    case NORMAL:
                        linkAttr = PaymentEnum.AMOUNT.getAttr();
                        break;
                    case BAD_TOTAL:
                        linkAttr = PaymentEnum.BAD_AMOUNT.getAttr();
                        break;
                    case FINISH_TOTAL:
                        linkAttr = PaymentEnum.REAL_AMOUNT.getAttr();
                        break;
                    default:
                        break;
                }
                break;
            case PURCHASE:
                switch (planTotalTypeEnum) {
                    case NORMAL:
                        linkAttr = PayPlanEnum.AMOUNT.getAttr();
                        break;
                    case BAD_TOTAL:
                        linkAttr = PayPlanEnum.BAD_AMOUNT.getAttr();
                        break;
                    case FINISH_TOTAL:
                        linkAttr = PayPlanEnum.REAL_AMOUNT.getAttr();
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
        if ( Objects.isNull(linkAttr) ) {
            LOG.error("关联的业务类型错误导致报错：xbbrefTypeEnum:" + xbbRefTypeEnum.getCode() + ",统计的业务类型：planTotalTypeEnum.alias" + planTotalTypeEnum.getAlias() + "、name" + planTotalTypeEnum.getName());
            throw new XbbException(BusinessTypeErrorCodeEnum.API_ERROR_361001);
        }
        return linkAttr;
    }
    
    /**
     * 获取付款计划/应收款需要查询的关联合同字段
     *
     * @param xbbRefTypeEnum
     * @return
     */
    private String getSheetLinkAttr(XbbRefTypeEnum xbbRefTypeEnum) {
        String linkAttr = PaymentSheetEnum.CONTRACT.getAttr();
        if ( Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.PURCHASE) ) {
            linkAttr = PaySheetEnum.LINK_PURCHASE.getAttr();
        }
        return linkAttr;
    }
    
    /**
     * 获取付款计划/应收款需要查询的关联合同字段
     *
     * @param xbbRefTypeEnum
     * @return
     */
    private String getPlanLinkAttr(XbbRefTypeEnum xbbRefTypeEnum) {
        String linkAttr = PaymentEnum.CONTRACT.getAttr();
        if ( Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.PURCHASE) ) {
            linkAttr = PayPlanEnum.LINK_PURCHASE.getAttr();
        }
        return linkAttr;
    }
    
    /**
     * @param xbbRefTypeEnum       业务类型(回款单/付款单)
     * @param formDataUpdateGetDTO
     * @param isTotalSheet         (是否统计付款金额/回款金额)
     * @param isTotalWriteOffPre   (是否统计回款单核销预收款金额/付款单核销预收款金额)
     * @param linkAttr             关联查询的字段(比如:回款单是合同字段/付款单是采购合同字段)
     * @return
     * @throws XbbException
     * @author chenshan
     * @date 2020-3-13 15:27
     */
    public Double getSheetTotalWriteOffAmount(XbbRefTypeEnum xbbRefTypeEnum, FormDataUpdateGetDTO formDataUpdateGetDTO, Boolean isTotalSheet, Boolean isTotalWriteOffPre, String linkAttr) throws XbbException {
//        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(xbbRefTypeEnum.getCode(), formDataUpdateGetDTO.getCorpid());
        FormDataSummaryDTO formDataSummaryDTO = new FormDataSummaryDTO();
        formDataSummaryDTO.setCorpid(formDataUpdateGetDTO.getCorpid());
//        BeanUtil.copyProperties(paasFormExplainEntity, formDataSummaryDTO, true);
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(formDataSummaryDTO.getCorpid(), xbbRefTypeEnum.getCode(), SaasMarkEnum.SAAS.getCode());
//        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        List<Object> writeOffPreTypeList = Arrays.asList(PaySheetTypeEnum.WRITE_OFF_PREPAY.getCode());
        String writeOffAmountAttr = PaySheetEnum.WRITE_OFF_AMOUNT.getAttr();
        List<Object> writeOffTypeList = Arrays.asList(PaySheetTypeEnum.WRITE_OFF_PAY.getCode());
        String amountAttr = PaySheetEnum.AMOUNT.getAttr();
        if ( Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.PAYMENT_SHEET) ) {
            writeOffPreTypeList = Arrays.asList(PaymentSheetTypeEnum.WRITE_OFF_PREPAYMENT.getCode());
            writeOffAmountAttr = PaymentSheetEnum.WRITE_OFF_AMOUNT.getAttr();
            writeOffTypeList = Arrays.asList(PaymentSheetTypeEnum.WRITE_OFF.getCode());
            amountAttr = PaymentSheetEnum.AMOUNT.getAttr();
        }
        return getSheetTotalWriteOffAmount(formDataSummaryDTO, indexTypeEnum, isTotalSheet, amountAttr, writeOffTypeList, isTotalWriteOffPre, writeOffAmountAttr, writeOffPreTypeList, linkAttr, formDataUpdateGetDTO.getDataId());
    }

    /**
     * 得到原单关联的红冲应收单据
     * @param payment
     * @param formDataUpdateGetDTO
     * @return java.lang.Double
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public Double getRedPaymentAmount(PaymentEntityExt payment, FormDataUpdateGetDTO formDataUpdateGetDTO) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", formDataUpdateGetDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        //排除资金改造前的原红冲数据（资金2期时已废弃原红冲，但是数据未删除）
        boolQueryBuilder.filter(boolQuery().mustNot(matchPhraseQuery(PaymentEnum.getEsAttr4Keyword(PaymentEnum.IS_RED), BasicConstant.ONE)));
        //只读红冲
        boolQueryBuilder.filter(termQuery(PaymentEnum.getEsAttr4Keyword(PaymentEnum.RECEIVABLE_IS_RED), BasicConstant.ONE));
        //关联原始应收字段关联了该id
        boolQueryBuilder.filter(termQuery(PaymentEnum.getEsAttr4Keyword(PaymentEnum.RECEIVABLES_ORIGIN_ID), payment.getId()));
        String sumField = PaymentEnum.getAttrConnectData(PaymentEnum.AMOUNT);
        return systemChartHelp.getDouble4Total(IndexTypeEnum.IDX_SAAS_PAYMENT, boolQueryBuilder, sumField);
    }

    /**
     * 获取坏账和红冲的统计金额
     * @param xbbRefTypeEnum
     * @param formDataUpdateGetDTO
     * @param isTotalRed
     * @param isTotalBad
     * @param linkAttr
     * @return
     * @throws XbbException
     */
    public Double getSheetRedAndBadAmount(XbbRefTypeEnum xbbRefTypeEnum, FormDataUpdateGetDTO formDataUpdateGetDTO, Boolean isTotalRed, Boolean isTotalBad, String linkAttr) throws XbbException {
//        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(xbbRefTypeEnum.getCode(), formDataUpdateGetDTO.getCorpid());
        FormDataSummaryDTO formDataSummaryDTO = new FormDataSummaryDTO();
//        BeanUtil.copyProperties(paasFormExplainEntity, formDataSummaryDTO, true);
        formDataSummaryDTO.setCorpid(formDataUpdateGetDTO.getCorpid());
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(formDataSummaryDTO.getCorpid(), xbbRefTypeEnum.getCode(), SaasMarkEnum.SAAS.getCode());
//        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        List<Object> redTypeList = Arrays.asList(PaymentSheetTypeEnum.RED_WRITE_OFF_PREPAYMENT.getCode(), PaymentSheetTypeEnum.RED_WRITE_OFF.getCode());
        List<Object> badTypeList = Arrays.asList(PaymentSheetTypeEnum.BAD_PAYMENT.getCode());
        //这边是红冲预收款核销(退到余额)
        List<Object> redWriteOffBalanceList = Arrays.asList(PaymentSheetTypeEnum.RED_WRITE_OFF_BALANCE.getCode());
        String redAttr = PaymentSheetEnum.AMOUNT.getAttr();
        String badAttr = PaymentSheetEnum.AMOUNT.getAttr();
        String writeOffBalanceAttr = PaymentSheetEnum.WRITE_OFF_AMOUNT.getAttr();
        if ( Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.PAY_SHEET) ) {
            redTypeList = Arrays.asList(PaySheetTypeEnum.RED_WRITE_OFF_PREPAY.getCode(), PaySheetTypeEnum.RED_WRITE_OFF_PAY.getCode());
            badTypeList = Arrays.asList(PaySheetTypeEnum.BAD_PAY.getCode());
            redAttr = PaySheetEnum.AMOUNT.getAttr();
            badAttr = PaySheetEnum.AMOUNT.getAttr();
        }
        return getSheetRedAndBadAmount(formDataSummaryDTO, indexTypeEnum, isTotalRed, redAttr, redTypeList, isTotalBad, badAttr, badTypeList, linkAttr,
                formDataUpdateGetDTO.getDataId(), redWriteOffBalanceList, writeOffBalanceAttr);
    }
    
    /**
     * 统计应收款/付款计划的计划回款/付款金额
     * @param xbbRefTypeEnum
     * @param formDataUpdateGetDTO
     * @param linkAttr
     * @param amountAttr
     * @return
     * @throws XbbException
     */
    public Double getPlanTotalRealAmount(XbbRefTypeEnum xbbRefTypeEnum, FormDataUpdateGetDTO formDataUpdateGetDTO, String linkAttr, String amountAttr) throws XbbException {
//        PaasFormExplainEntity paymentExplainEntity = paasFormExplainModel.getByBusinessType(xbbRefTypeEnum.getCode(), formDataUpdateGetDTO.getCorpid());
        FormDataSummaryDTO formDataSummaryDTO = new FormDataSummaryDTO();
//        BeanUtil.copyProperties(paymentExplainEntity, formDataSummaryDTO, true);
        formDataSummaryDTO.setCorpid(formDataUpdateGetDTO.getCorpid());
        List<ConditionsEntityExt> conditions = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        conditions.add(new ConditionsEntityExt(FieldTypeEnum.FLOW_STATUS.getAlias(), "", FieldTypeEnum.FLOW_STATUS.getType(), ConditionEnum.IN.getSymbol(), Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
        conditions.add(new ConditionsEntityExt(linkAttr, "", FieldTypeEnum.TEXT.getType(), ConditionEnum.EQUAL.getSymbol(), Collections.singletonList(formDataUpdateGetDTO.getDataId())));
        formDataSummaryDTO.setConditions(conditions);
        
        IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(formDataSummaryDTO.getCorpid(), xbbRefTypeEnum.getCode(), SaasMarkEnum.SAAS.getCode());
//        List<FieldAttrEntity> explainList = JSONArray.parseArray(paymentExplainEntity.getExplains(), FieldAttrEntity.class);
        return getPlanTotalRealAmount(indexTypeEnum, formDataSummaryDTO, amountAttr);
    }
    
    /**
     * @param formDataSummaryDTO
     * @param indexTypeEnum
     * @param isTotalSheet        (是否统计付款金额/回款金额)
     * @param amountAttr          回款金额字段(回款单为num_1，付款单为num_1)
     * @param writeOffTypeList    回/付款金额的值（回款单为1，付款单为1）
     * @param isTotalWriteOffPre  (是否统计回款单核销预收款金额/付款单核销预收款金额)
     * @param writeOffPreTypeList 核销预收款的字段值 （回款单为2，付款单为2）
     * @param writeOffAmountAttr  核销预收款的字段（回款单为num_7，付款单为num_2）
     * @param linkAttr            关联字段(比如回款单可以关联的字段为合同/应收款，付款单可以关联的字段为采购合同/付款计划)
     * @param linkId              关联字段的值(比如回款单可以关联的字段为合同/应收款的id，付款单可以关联的字段为采购合同/付款计划的id)
     * @return
     * @throws XbbException
     * @author chenshan
     */
    private Double getSheetTotalWriteOffAmount(FormDataSummaryDTO formDataSummaryDTO, IndexTypeEnum indexTypeEnum, Boolean isTotalSheet, String amountAttr, List<Object> writeOffTypeList, Boolean isTotalWriteOffPre, String writeOffAmountAttr, List<Object> writeOffPreTypeList, String linkAttr, Long linkId) throws XbbException {
        String typeAttr = PaymentConstant.ATTR_SHEET_TYPE;
        Double writeOffAmount = 0D;
        //查询回款单的核销预收款金额
        List<ConditionsEntityExt> conditions = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        conditions.add(new ConditionsEntityExt(FieldTypeEnum.SHEET_ALONE.getAlias(), "", FieldTypeEnum.SHEET_ALONE.getType(), ConditionEnum.IN.getSymbol(), Arrays.asList(SheetAloneEnum.NORMAL.getCode(), SheetAloneEnum.CHILD.getCode())));
        conditions.add(new ConditionsEntityExt(FieldTypeEnum.FLOW_STATUS.getAlias(), "", FieldTypeEnum.FLOW_STATUS.getType(), ConditionEnum.IN.getSymbol(), Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
        ConditionsEntityExt contractCondition = new ConditionsEntityExt(linkAttr, "", FieldTypeEnum.TEXT.getType(),  ConditionEnum.IN.getSymbol(), Collections.singletonList(linkId));
        conditions.add(contractCondition);
        ConditionsEntityExt condition = new ConditionsEntityExt();
        List<AggSumDTO> sumList = new ArrayList<>();
        if ( isTotalWriteOffPre ) {
            condition = new ConditionsEntityExt(typeAttr, "", FieldTypeEnum.COMBO.getType(), ConditionEnum.EQUAL.getSymbol(), writeOffPreTypeList);
            conditions.add(condition);
            formDataSummaryDTO.setConditions(conditions);
            
            NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            //解析查询条件
            EsUtil.parseCondition(boolQueryBuilder, formDataSummaryDTO.getConditions(), formDataSummaryDTO.getRel(), formDataSummaryDTO.getCorpid(), formDataSummaryDTO.getBusinessType());
            // 拼接appId，菜单id等数据
//            EsUtil.getTermQuery(boolQueryBuilder, formDataSummaryDTO, true);
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + "." + StringConstant.KEY_WORD, formDataSummaryDTO.getCorpid()));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
            NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();
            AggSumDTO aggSumDTO = new AggSumDTO();
            aggSumDTO.setAttr(writeOffAmountAttr);
            aggSumDTO.setField("data." + writeOffAmountAttr);
            // 累加字段
            sumList.add(aggSumDTO);
            List<AggSumVO> writeOffAmountSumList = esHelper.aggSumByField(indexTypeEnum.getIndex(), indexTypeEnum.getType(), sumList, searchQuery);
            sumList.clear();
            if ( CollectionsUtil.isNotEmpty(writeOffAmountSumList) ) {
                writeOffAmount = Arith.add(writeOffAmount, Double.valueOf(writeOffAmountSumList.get(0).getValue().toString()));
            }
        }
        if ( isTotalSheet ) {
            //查询回/付款单的回款金额
            conditions.remove(condition);
            conditions.remove(contractCondition);
            contractCondition = new ConditionsEntityExt(linkAttr, "", FieldTypeEnum.TEXT.getType(), ConditionEnum.IN.getSymbol(), Collections.singletonList(linkId));
            conditions.add(contractCondition);
            condition = new ConditionsEntityExt(typeAttr, "", FieldTypeEnum.COMBO.getType(), ConditionEnum.EQUAL.getSymbol(), writeOffTypeList);
            conditions.add(condition);
            formDataSummaryDTO.setConditions(conditions);
            
            NativeSearchQueryBuilder paymentSheetSearchQueryBuilder = new NativeSearchQueryBuilder();
            BoolQueryBuilder paymentSheetBoolQueryBuilder = boolQuery();
            //解析查询条件
            EsUtil.parseCondition(paymentSheetBoolQueryBuilder, formDataSummaryDTO.getConditions(), formDataSummaryDTO.getRel(), formDataSummaryDTO.getCorpid(), formDataSummaryDTO.getBusinessType());
            // 拼接appId，菜单id等数据
//            EsUtil.getTermQuery(paymentSheetBoolQueryBuilder, formDataSummaryDTO, true);
            paymentSheetBoolQueryBuilder.filter(termQuery(StringConstant.CORPID + "." + StringConstant.KEY_WORD, formDataSummaryDTO.getCorpid()));
            paymentSheetBoolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            paymentSheetSearchQueryBuilder.withQuery(paymentSheetBoolQueryBuilder);
            NativeSearchQuery paymentSheetSearchQuery = paymentSheetSearchQueryBuilder.build();
            AggSumDTO aggSumDTO = new AggSumDTO();
            aggSumDTO.setAttr(amountAttr);
            aggSumDTO.setField("data." + amountAttr);
            // 累加字段
            sumList.add(aggSumDTO);
            List<AggSumVO> amountSumList = esHelper.aggSumByField(indexTypeEnum.getIndex(), indexTypeEnum.getType(), sumList, paymentSheetSearchQuery);
            if ( CollectionsUtil.isNotEmpty(amountSumList) ) {
                writeOffAmount = Arith.add(writeOffAmount, Double.valueOf(amountSumList.get(0).getValue().toString()));
            }
        }
        return writeOffAmount;
    }
    
    /**
     * 获取付款单的红冲和坏账金额
     *
     * @param formDataSummaryDTO
     * @param indexTypeEnum
     * @param isTotalRed         支付统计红冲
     * @param redAttr            红冲字段
     * @param redTypeList        红冲类型
     * @param isTotalBad         是否统计坏账
     * @param badAttr            坏账字段
     * @param badTypeList        坏账类型
     * @param linkAttr           关联字段(比如回款单可以关联的字段为合同/应收款，付款单可以关联的字段为采购合同/付款计划)
     * @param linkId             关联字段的值(比如回款单可以关联的字段为合同/应收款的id，付款单可以关联的字段为采购合同/付款计划的id)
     * @param redWriteOffBalanceList 红冲预收款核销(退到余额)
     * @param writeOffBalanceAttr 红冲预收款核销(退到余额)这种情况需统计attr
     * @return
     * @throws XbbException
     */
    private Double getSheetRedAndBadAmount(FormDataSummaryDTO formDataSummaryDTO, IndexTypeEnum indexTypeEnum, Boolean isTotalRed, String redAttr, List<Object> redTypeList, Boolean isTotalBad, String badAttr, List<Object> badTypeList, String linkAttr,
                                           Long linkId, List<Object> redWriteOffBalanceList, String writeOffBalanceAttr) throws XbbException {
        Double writeOffAmount = 0D;
        String typeAttr = PaymentConstant.ATTR_SHEET_TYPE;
        List<AggSumDTO> sumList = new ArrayList<>();
        List<ConditionsEntityExt> conditions = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        conditions.add(new ConditionsEntityExt(FieldTypeEnum.SHEET_ALONE.getAlias(), "", FieldTypeEnum.SHEET_ALONE.getType(), ConditionEnum.IN.getSymbol(), Arrays.asList(SheetAloneEnum.NORMAL.getCode(), SheetAloneEnum.CHILD.getCode())));
        conditions.add(new ConditionsEntityExt(FieldTypeEnum.FLOW_STATUS.getAlias(), "", FieldTypeEnum.FLOW_STATUS.getType(), ConditionEnum.IN.getSymbol(), Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
        ConditionsEntityExt contractCondition = new ConditionsEntityExt(linkAttr, "", FieldTypeEnum.LINK_BUSINESS_MULTI.getType(), ConditionEnum.IN.getSymbol(), Collections.singletonList(linkId));
        conditions.add(contractCondition);
        ConditionsEntityExt condition = new ConditionsEntityExt(typeAttr, "", FieldTypeEnum.COMBO.getType(), ConditionEnum.IN.getSymbol(), redTypeList);
        conditions.add(condition);
        formDataSummaryDTO.setConditions(conditions);
        ////查询回款单的红冲金额
        if ( isTotalRed ) {
            BoolQueryBuilder redBoolQueryBuilder = boolQuery();
            //解析查询条件
            EsUtil.parseCondition(redBoolQueryBuilder, formDataSummaryDTO.getConditions(), formDataSummaryDTO.getRel(), formDataSummaryDTO.getCorpid(), formDataSummaryDTO.getBusinessType());
            NativeSearchQuery redSearchQuery = getNativeSearchQuery(redBoolQueryBuilder, formDataSummaryDTO);
            // 累加字段
            getAggSumDTO(redAttr, sumList);
            List<AggSumVO> redAmountSumList = esHelper.aggSumByField(indexTypeEnum.getIndex(), indexTypeEnum.getType(), sumList, redSearchQuery);
            Double redAmount = 0D;
            if ( CollectionsUtil.isNotEmpty(redAmountSumList) ) {
                redAmount = Double.valueOf(redAmountSumList.get(0).getValue().toString());
                writeOffAmount = Arith.add(writeOffAmount, redAmount);
            }
            if (Objects.equals(indexTypeEnum, IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET)) {
                //统计红冲预收款核销(退到余额)，因为很多都是公用的，所以这边就只对conditions做一下处理
                BoolQueryBuilder redBalanceBoolQueryBuilder = boolQuery();
                conditions.remove(condition);
                ConditionsEntityExt redBalanceCondition = new ConditionsEntityExt(typeAttr, "", FieldTypeEnum.COMBO.getType(), ConditionEnum.IN.getSymbol(), redWriteOffBalanceList);
                conditions.add(redBalanceCondition);
                formDataSummaryDTO.setConditions(conditions);
                EsUtil.parseCondition(redBalanceBoolQueryBuilder, formDataSummaryDTO.getConditions(), formDataSummaryDTO.getRel(), formDataSummaryDTO.getCorpid(), formDataSummaryDTO.getBusinessType());
                NativeSearchQuery redBalanceSearchQuery = getNativeSearchQuery(redBalanceBoolQueryBuilder, formDataSummaryDTO);
                // 累加字段
                sumList.clear();
                getAggSumDTO(writeOffBalanceAttr, sumList);
                List<AggSumVO> redBalanceAmountSumList = esHelper.aggSumByField(indexTypeEnum.getIndex(), indexTypeEnum.getType(), sumList, redBalanceSearchQuery);
                if (CollectionsUtil.isNotEmpty(redBalanceAmountSumList)) {
                    Double redBalanceAmount = Double.valueOf(redBalanceAmountSumList.get(0).getValue().toString());
                    writeOffAmount = Arith.add(writeOffAmount, redBalanceAmount);
                }
                conditions.remove(redBalanceCondition);
            }

        }
        conditions.remove(condition);
        sumList.clear();
        conditions.remove(contractCondition);
        //查询回/付款单的坏账金额2
        if ( isTotalBad ) {
            contractCondition = new ConditionsEntityExt(linkAttr, "", FieldTypeEnum.LINK_BUSINESS_MULTI.getType(), ConditionEnum.IN.getSymbol(), Collections.singletonList(linkId));
            conditions.add(contractCondition);
            condition = new ConditionsEntityExt(typeAttr, "", FieldTypeEnum.COMBO.getType(), ConditionEnum.EQUAL.getSymbol(), badTypeList);
            conditions.add(condition);
            formDataSummaryDTO.setConditions(conditions);

            BoolQueryBuilder badBoolQueryBuilder = boolQuery();
            //解析查询条件
            EsUtil.parseCondition(badBoolQueryBuilder, formDataSummaryDTO.getConditions(), formDataSummaryDTO.getRel(), formDataSummaryDTO.getCorpid(), formDataSummaryDTO.getBusinessType());
            // 拼接appId，菜单id等数据
//            EsUtil.getTermQuery(badBoolQueryBuilder, formDataSummaryDTO, true);
            NativeSearchQuery badSearchQuery = getNativeSearchQuery(badBoolQueryBuilder, formDataSummaryDTO);
            // 累加字段
            getAggSumDTO(badAttr, sumList);
            List<AggSumVO> badAmountSumList = esHelper.aggSumByField(indexTypeEnum.getIndex(), indexTypeEnum.getType(), sumList, badSearchQuery);
            if ( CollectionsUtil.isNotEmpty(badAmountSumList) ) {
                writeOffAmount = Arith.add(writeOffAmount, Double.valueOf(badAmountSumList.get(0).getValue().toString()));
            }
        }
        return writeOffAmount;
    }

    /**
     * 封装sum参数
     *
     * @return
     */
    private void getAggSumDTO(String attr, List<AggSumDTO> sumList) {
        AggSumDTO aggSumDTO = new AggSumDTO();
        aggSumDTO.setAttr(attr);
        aggSumDTO.setField("data." + attr);
        sumList.add(aggSumDTO);
    }

    /**
     * 返回一个es中的查询条件
     *
     * @param boolQueryBuilder
     * @param formDataSummaryDTO
     * @return
     */
    private NativeSearchQuery getNativeSearchQuery(BoolQueryBuilder boolQueryBuilder, FormDataSummaryDTO formDataSummaryDTO) {
        NativeSearchQueryBuilder redSearchQueryBuilder = new NativeSearchQueryBuilder();
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + "." + StringConstant.KEY_WORD, formDataSummaryDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        redSearchQueryBuilder.withQuery(boolQueryBuilder);
        NativeSearchQuery redSearchQuery = redSearchQueryBuilder.build();
        return redSearchQuery;
    }
    
    /**
     * 应收款/付款计划的计划回款/付款金额计算
     *
     * @param indexTypeEnum
     * @param formDataSummaryDTO
     * @param amountAttr         需要统计的字段
     * @return
     * @throws XbbException
     */
    private Double getPlanTotalRealAmount(IndexTypeEnum indexTypeEnum, FormDataSummaryDTO formDataSummaryDTO, String amountAttr) throws XbbException {
        Double realAmount = 0D;
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        //解析查询条件
        EsUtil.parseCondition(boolQueryBuilder, formDataSummaryDTO.getConditions(), formDataSummaryDTO.getRel(), formDataSummaryDTO.getCorpid(), formDataSummaryDTO.getBusinessType());
        // 拼接appId，菜单id等数据
//        EsUtil.getTermQuery(boolQueryBuilder, formDataSummaryDTO, true);
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + "." + StringConstant.KEY_WORD, formDataSummaryDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();
        List<AggSumDTO> sumList = new ArrayList<>();
        // 累加字段
        AggSumDTO aggSumDTO = new AggSumDTO();
        aggSumDTO.setAttr(amountAttr);
        aggSumDTO.setField("data." + amountAttr);
        sumList.add(aggSumDTO);
        List<AggSumVO> aggSumList = esHelper.aggSumByField(indexTypeEnum.getIndex(), indexTypeEnum.getType(), sumList, searchQuery);
        if ( CollectionsUtil.isNotEmpty(aggSumList) ) {
            realAmount = Arith.add(realAmount, Double.valueOf(aggSumList.get(0).getValue().toString()));
        }
        return realAmount;
    }

    /**
     * 余乾原有未注释逻辑，不做更改，兼容一下【关联回款计划】关闭时审批详情报错的情况（因为未关闭时，data内该字段可能被格式化为JSONObject；而该字段未启用则又未格式化，为普通字符串格式）
     * @param data 数据data
     * @param corpid 公司id
     * @author 余乾
     * @since v1.0
     * @version 重构线上bug处理 by zcp
     */
    public void setPrePaymentSheetType(JSONObject data, String corpid){
        String relationshipType = getRelationshipType(data, InvoiceEnum.PAYMENT_RELATIONSHIP.getAttr());
        if (Objects.equals(relationshipType, PaymentRelationshipEnum.PAYMENT_SHEET.getCode())) {
            List<Long> idList = new ArrayList<>();
            JSONArray paymentSheetArray = data.getJSONArray(InvoiceEnum.PAYMENT_SHEET_ID.getAttr());
            if (CollectionsUtil.isNotEmpty(paymentSheetArray)) {
                for (int i = 0; i < paymentSheetArray.size(); i++) {
                    JSONObject paymentSheetObject = paymentSheetArray.getJSONObject(i);
                    Long id = paymentSheetObject.getLong(BasicConstant.ID);
                    idList.add(id);
                }
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("idIn", idList);
                param.put("corpid", corpid);
                param.put("del", DelEnum.NORMAL.getDel());
                List<PaymentSheetEntityExt> paymentSheetEntityExts = paymentSheetModel.findEntitys(param);
                Map<Long, String> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

                paymentSheetEntityExts.forEach(item -> {
                    JSONObject paymentSheetObject = item.getData();
                    if (Objects.nonNull(paymentSheetObject.getString(PaymentSheetEnum.PAYMENT_SHEET_TYPE.getAttr()))) {
                        map.put(item.getId(), item.getData().getString(PaymentSheetEnum.PAYMENT_SHEET_TYPE.getAttr()));
                    }
                });
                for (int i = 0; i < paymentSheetArray.size(); i++) {
                    JSONObject paymentSheetObject = paymentSheetArray.getJSONObject(i);
                    Long id = paymentSheetObject.getLong(BasicConstant.ID);
                    idList.add(id);
                }
                for (int i = 0; i < paymentSheetArray.size(); i++) {
                    JSONObject paymentSheetObject = paymentSheetArray.getJSONObject(i);
                    Long id = paymentSheetObject.getLong(BasicConstant.ID);
                    String type = map.getOrDefault(id, SheetTypeEnum.WRITE_OFF.getCode());
                    paymentSheetObject.put(InvoiceConstant.PAYMENT_SHEET_TYPE, type);
                }
            }
        }
    }

    /**
     * 余乾原有未注释逻辑，不做更改，兼容一下【关联付款计划】关闭时审批详情报错的情况（因为未关闭时，data内该字段可能被格式化为JSONObject；而该字段未启用则又未格式化，为普通字符串格式）
     * @param data 数据data
     * @param corpid 公司id
     * @author 余乾
     * @since v1.0
     * @version 重构线上bug处理 by zcp
     */
    public void setPrePaySheetType(JSONObject data,String corpid){
        String relationshipType = getRelationshipType(data, PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr());
        if (Objects.equals(relationshipType, PayRelationshipEnum.PAY_SHEET.getCode())) {
            List<Long> idList = new ArrayList<>();
            JSONArray paySheetArray = data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr());
            if (CollectionsUtil.isNotEmpty(paySheetArray)) {
                for (int i = 0; i < paySheetArray.size(); i++) {
                    JSONObject paySheetObject = paySheetArray.getJSONObject(i);
                    Long id = paySheetObject.getLong(BasicConstant.ID);
                    idList.add(id);
                }
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("idIn", idList);
                param.put("corpid", corpid);
                param.put("del", DelEnum.NORMAL.getDel());
                List<PayPlanSheetEntityExt> payPlanSheetEntityExts = paySheetModel.findEntitys(param);
                Map<Long, String> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

                payPlanSheetEntityExts.forEach(item -> {
                    JSONObject paySheetObject = item.getData();
                    if (Objects.nonNull(paySheetObject.getString(PaySheetEnum.PAY_SHEET_TYPE.getAttr()))) {
                        map.put(item.getId(), item.getData().getString(PaySheetEnum.PAY_SHEET_TYPE.getAttr()));
                    }
                });
                for (int i = 0; i < paySheetArray.size(); i++) {
                    JSONObject paySheetObject = paySheetArray.getJSONObject(i);
                    Long id = paySheetObject.getLong(BasicConstant.ID);
                    idList.add(id);
                }
                for (int i = 0; i < paySheetArray.size(); i++) {
                    JSONObject paySheetObject = paySheetArray.getJSONObject(i);
                    Long id = paySheetObject.getLong(BasicConstant.ID);
                    String type = map.getOrDefault(id, SheetTypeEnum.WRITE_OFF_PAY.getCode());
                    paySheetObject.put(InvoiceConstant.PAY_SHEET_TYPE, type);
                }
            }
        }
    }

    /**
     * 审批内销项发票/进项发票获取relationshipType（data内数据可能被格式化为JSONObject；如果字段未启用则又未格式化，为普通字符串格式）
     * @param data 销项发票/进项发票审批内data
     * @param attr data内关联回款类型/关联付款类型的字段名
     * @return java.lang.String
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private String getRelationshipType(JSONObject data, String attr) {
        Object object = data.get(attr);
        String relationshipType = null;
        if (Objects.isNull(object)) {
            return relationshipType;
        }
        if (object instanceof JSONObject) {
            JSONObject payRelationshipType = (JSONObject) object;
            relationshipType = payRelationshipType.getString(BasicConstant.VALUE);
        } else if (object instanceof String || object instanceof Integer) {
            relationshipType = object.toString();
        } else if(object instanceof ItemPoJo){
            relationshipType = ((ItemPoJo) object).getValue().toString();
        }
        return relationshipType;
    }
}
